﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;



namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            DirectoryInfo d = new DirectoryInfo("books");
//            FileInfo[] rgFiles = d.GetFiles("*", SearchOption.TopDirectoryOnly);
            FileInfo[] rgFiles = d.GetFiles("*", SearchOption.AllDirectories);
            Parser myparser = new Parser("stop.txt");
            foreach (FileInfo fi in rgFiles)
            {
                //Console.Write(fi.Name + "\t");
                myparser.Process_file(fi.FullName);
                float x = ((float)myparser.total_nesses / (float)myparser.total_words);
                float y = (((float)myparser.total_ness + (float)myparser.total_nesses) / (float)myparser.total_words);
                //only 5
                //              Console.Write("\t{0, 6:F8}\t{1, 6:F8}\t", x, y);
            //    Console.WriteLine("{0}\t{1, 6:F8}\t", x, y);
                IDictionaryEnumerator de = myparser.GetWordsByOccurrenceEnumerator();

                //   Console.WriteLine(String.Format("Word usage sorted by occurrence ({0} unique words)", myparser.UniqueWords));
                int cnt = 0;
                int num_rare_words = 0;
                while (de.MoveNext())
                {
                    WordOccurrence wo = (WordOccurrence)de.Key;
                    //           Console.Write("({0}){1}", ((WordOccurrence)de.Key).Occurrences, ((WordOccurrence)de.Key).Word);
                    //Console.WriteLine("({0}){1}", ((WordOccurrence)de.Key).Occurrences, ((WordOccurrence)de.Key).Word);
                    if (wo.Occurrences < 3) num_rare_words += wo.Occurrences;
                    cnt++;
                    //    if (cnt >= 4) break;
                    //                    Console.Write(", ");
                }
//                Console.WriteLine("Words : {0}", myparser.total_words);
  //              Console.WriteLine("Nesses : {0}", myparser.total_ness);
    //            Console.WriteLine("Nesseses : {0}", myparser.total_nesses);
      //          Console.WriteLine("Rare nesses : {0}", num_rare_words);
        //        Console.WriteLine("{0,6:F8}", ((double)num_rare_words * 1000.0) / (double)myparser.total_words);
                Console.WriteLine("{0,6:F8} \t " + fi.FullName  , ((double)cnt * 100000.0) / (double)myparser.total_words);
            }


            //for each file
            //show stat
        }
    }

    class Parser
    {
        //stoplist
        ArrayList ar = new ArrayList();
        SortedList wordCounter;
        public int total_words;
        public int total_ness;
        public int total_nesses;

        public Parser(string stoplist)
        {

            TextReader tr = new StreamReader(stoplist);
            string s;
            while ((s = tr.ReadLine()) != null)
            {
                ar.Add(s.ToLower());
                // Console.WriteLine(s);
            }
            tr.Close();
        }
        public void Process_file(string filename)
        {
            total_words = 0;
            total_ness = 0;
            total_nesses = 0;

            wordCounter = new SortedList();
            // Attempt to open the input file for read-only access
            FileStream fsIn = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
            using (StreamReader sr = new StreamReader(fsIn))
            {
                // Process every line in the file
                for (String Line = sr.ReadLine(); Line != null; Line = sr.ReadLine())
                {

                    String[] Words = Line.Split(null);  // Split the line into words

                    for (int Word = 0; Word < Words.Length; Word++)
                    {
                        string str = Words[Word].ToLower();
                        if (str.Length > 0)
                        {	// Don't count empty strings
                            total_words++;
                            string temp_for_dict = str;
                            if (str.EndsWith("nesses"))
                            {
                                total_nesses++;
                                temp_for_dict = str.Remove(str.Length - 2);
                                // Console.WriteLine(str);
                            }
                            if (str.EndsWith("ness") || str.EndsWith("nesse"))
                            if(!ar.Contains(temp_for_dict))
                            {
                                if (str.EndsWith("nesse"))
                                {
                                    total_ness++;
                                }
                                if (str.EndsWith("ness")) total_ness++;
                                if (str.EndsWith("nesses"))
                                {
                                    total_nesses++;
                                    str = str.Remove(str.Length - 2);
                                    // Console.WriteLine(str);
                                }

                                if (str.EndsWith("ness") || str.EndsWith("nesse"))
                                {
                                    if (!wordCounter.ContainsKey(Words[Word]))
                                    {
                                        // If we've never seen this word before, add it to the sorted list with a count of 1
                                        wordCounter.Add(Words[Word], 1);
                                    }
                                    else
                                    {
                                        // If we have seen this word before, just increment its count
                                        wordCounter[Words[Word]] = (Int32)wordCounter[Words[Word]] + 1;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }


        // print stats ---------------------------------------------------
        public IDictionaryEnumerator GetWordsAlphabeticallyEnumerator()
        {
            return (IDictionaryEnumerator)wordCounter.GetEnumerator();
        }

        // Returns an enumerator for the words (sorted by occurrence)
        public IDictionaryEnumerator GetWordsByOccurrenceEnumerator()
        {
            // To create a list of words sorted by occurrence, we need another SortedList object
            SortedList sl = new SortedList();

            // Now, we'll iterate through the words alphabetically
            IDictionaryEnumerator de = GetWordsAlphabeticallyEnumerator();

            while (de.MoveNext())
            {
                // For each word, we create a new WordOccurrence object which
                // contains the word and its occurrence value.
                // The WordOccurrence class contains a CompareTo method which knows
                // to sort WordOccurrence objects by occurrence value and then alphabetically by the word itself.
                sl.Add(new WordOccurrence((int)de.Value, (string)de.Key), null);
            }

            // Return an enumerator for the words (sorted by occurrence)
            return (IDictionaryEnumerator)sl.GetEnumerator();
            //  sl.re
        }

        public int UniqueWords
        {
            get { return wordCounter.Count; }
        }



    }

    public class WordOccurrence : IComparable
    {
        // Members indicating the number of times this word occurred and the word itself
        private int occurrences;

        private String word;

        // Constructor
        public WordOccurrence(int occurrences, String word)
        {
            this.occurrences = occurrences;
            this.word = word;
        }

        // Sorts two WordOccurrence objects by occurrence first, then by word
        public int CompareTo(Object o)
        {
            // Compare the occurance of the two objects
            //            int n = occurrences - ((WordOccurrence)o).occurrences;
            int n = ((WordOccurrence)o).occurrences - occurrences;

            if (n == 0)
            {
                // Both objects have the same ccurrance, sort alphabetically by word
                n = String.Compare(word, ((WordOccurrence)o).word, false, Thread.CurrentThread.CurrentCulture);
            }

            return (n);
        }

        // Return the occurrence value of this word
        public int Occurrences { get { return occurrences; } }

        // Return this word
        public String Word { get { return word; } }

        public override bool Equals(Object obj)
        {
            if (!(obj is WordOccurrence))
                return false;

            return (this.CompareTo(obj) == 0);
        }

        // Omitting getHashCode violates FxCop rule: EqualsOverridesRequireGetHashCodeOverride.
        public override int GetHashCode()
        {
            return occurrences + word.GetHashCode();
        }

        public static bool operator ==(WordOccurrence wo1, WordOccurrence wo2)
        {
            return wo1.Equals(wo2);
        }

        public static bool operator !=(WordOccurrence wo1, WordOccurrence wo2)
        {
            return !(wo1 == wo2);
        }

        public static bool operator <(WordOccurrence wo1, WordOccurrence wo2)
        {
            return (wo1.CompareTo(wo2) < 0);
        }

        public static bool operator >(WordOccurrence wo1, WordOccurrence wo2)
        {
            return (wo1.CompareTo(wo2) > 0);
        }
    }


}
